package net.youpoint.core.beans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;

import net.youpoint.core.beans.Question.Answer;
import net.youpoint.dao.QuestionDao;
import net.youpoint.dao.impl.QuestionDaoImpl;
import net.youpoint.entity.OptionEntity;
import net.youpoint.entity.QuestionEntity;
import net.youpoint.util.Helper;

import org.primefaces.event.ToggleEvent;

import com.google.appengine.api.datastore.Key;

@ManagedBean(name = "questionListBean")
@SessionScoped
public class QuestionList implements Serializable {

	private static final long serialVersionUID = 3114670105233347332L;

	/**
	 * key flags of cookie string
	 * 
	 * @author public
	 * 
	 */
	private enum CookieFlag {
		VOTED;
	}

	final QuestionDao questionDao = new QuestionDaoImpl();

	private Answer answer = new Answer();
	private Question question = reinitQuestion();

	private Answer selectedAnswer;
	private Question selectedQuestion;

	private Collection<Question> questions = new ArrayList<Question>();

	private boolean showDeleted = false;

	@PostConstruct
	public void init() {
		reloadQuestions();
	}

	/**
	 * reload questions from data storage
	 * 
	 */
	public void reloadQuestions() {

		this.questions.clear();

		List<QuestionEntity> list = new ArrayList<QuestionEntity>();

		if (this.showDeleted) {
			list = this.questionDao.listAll();
		} else {
			list = this.questionDao.list();
		}

		// System.out.println("--- questions ---");

		for (final QuestionEntity entity : list) {

			final Key eKey = entity.getKey();

			final Question que = new Question();
			que.setTxt(entity.getText());
			que.setEntityKey(eKey);
			que.setDtCreate(entity.getCreateDate());
			que.setDtDelete(entity.getDeleteDate());
			que.setVoted(false);

			final List<Answer> answers = que.getAnswers();

			final List<OptionEntity> options = entity.getOptions();
			for (final OptionEntity optionEntity : options) {

				final Answer ans = new Answer();
				ans.setEntityKey(optionEntity.getKey());
				ans.setPop(optionEntity.getPop());
				ans.setTxt(optionEntity.getText());

				answers.add(ans);
			}

			final String strKeyId = String.valueOf(eKey.getId());

			final String cookieValue = Helper.getCookieValue(CookieFlag.VOTED
					.name());
			if ((cookieValue != null) && (cookieValue.contains(strKeyId))) {
				que.setVoted(true);
			}

			// System.out.println("qe id =" + que.getEntityKey().getId() +
			// "; voted =" + que.isVoted() + ";");

			this.questions.add(que);
		}

		if ((this.questions != null) && (this.questions.size() > 0)) {
			this.selectedQuestion = this.questions.iterator().next();

			final List<Answer> answers = this.selectedQuestion.getAnswers();
			if ((answers != null) && (answers.size() > 0)) {
				this.selectedAnswer = answers.get(0);
			}

		}

	}

	public void newQuestion(final ToggleEvent event) {
		this.question = reinitQuestion();
	}

	public void newQuestion(final ActionEvent event) {
		this.question = reinitQuestion();
	}

	private static Question reinitQuestion() {
		final Question res = new Question();
		final List<Answer> answers = res.getAnswers();

		answers.add(new Answer("answer one", 0));
		answers.add(new Answer("answer two", 0));

		return res;
	}

	/**
	 * vote for specific answer in the specific question
	 * 
	 */
	public void vote() {

		final Key entityKey = this.selectedQuestion.getEntityKey();
		final String strKeyId = String.valueOf(entityKey.getId());

		final QuestionEntity qe = this.questionDao.find(entityKey);

		final Key selectedKey = this.selectedAnswer.getEntityKey();

		this.selectedQuestion.setVoted(true);

		// check before vote
		String cookieValue = Helper.getCookieValue(CookieFlag.VOTED.name());
		if (cookieValue != null) {
			if (cookieValue.contains(strKeyId)) {
				return;
			}
		}

		final List<OptionEntity> options = qe.getOptions();
		for (final OptionEntity tmpOptionEntity : options) {
			final Key key = tmpOptionEntity.getKey();
			if (key.equals(selectedKey)) {
				int pop = tmpOptionEntity.getPop();
				pop += 1;
				tmpOptionEntity.setPop(pop);

				this.selectedAnswer.setPop(pop);
				break;
			}
		}

		this.questionDao.save(qe);

		// save user voted the question
		if (cookieValue == null) {
			cookieValue = strKeyId + "@";
		} else {
			cookieValue += strKeyId + "@";
		}

		Helper.setCookieValue(CookieFlag.VOTED.name(), cookieValue, "",
				365 * 24 * 60 * 60);
	}

	/**
	 * save current question
	 * 
	 */
	public void saveQuestion() {
		QuestionEntity qe = this.questionDao.find(this.question.getEntityKey());

		if (qe == null) {
			qe = new QuestionEntity();
		}

		qe.setText(this.question.getTxt());
		qe.setCreateDate(this.question.getDtCreate());

		final List<OptionEntity> options = qe.getOptions();

		final List<OptionEntity> removedOptions = new ArrayList<OptionEntity>(
				options); // outdated records

		final List<Answer> answers = this.question.getAnswers();
		for (final Answer ans : answers) {

			boolean foundInDB = false;
			for (final OptionEntity opt : options) {
				final Key optKey = opt.getKey();
				if ((optKey != null) && (optKey.equals(ans.getEntityKey()))) {

					opt.setQuestion(qe);
					opt.setPop(ans.getPop());
					opt.setText(ans.getTxt());

					foundInDB = true;

					removedOptions.remove(opt);
					break;
				}
			}

			if (!foundInDB) {
				final OptionEntity opt = new OptionEntity();

				opt.setKey(ans.getEntityKey());
				opt.setQuestion(qe);
				opt.setPop(ans.getPop());
				opt.setText(ans.getTxt());

				options.add(opt);
			}// add new
		}

		options.removeAll(removedOptions);

		this.questionDao.save(qe);

		this.question = reinitQuestion();

		reloadQuestions();
	}

	public void markQuestionDeleted() {
		final QuestionEntity queEntity = this.questionDao.find(this.question
				.getEntityKey());

		this.questionDao.markDeleted(queEntity);

		reloadQuestions();
	}

	public void deleteQuestion() {
		final QuestionEntity queEntity = this.questionDao.find(this.question
				.getEntityKey());

		this.questionDao.totalDelete(queEntity);

		reloadQuestions();
	}

	public void newAnswer() {
		this.answer = new Answer("enter new option here...", 0);
	}

	public Question getQuestion() {
		return this.question;
	}

	public Answer getAnswer() {
		return this.answer;
	}

	public void setAnswer(final Answer answer) {
		this.answer = answer;
	}

	public void setQuestion(final Question question) {
		this.question = question;
	}

	public boolean isShowDeleted() {
		return this.showDeleted;
	}

	public void setShowDeleted(final boolean showDeleted) {
		this.showDeleted = showDeleted;
	}

	public Answer getSelectedAnswer() {
		return this.selectedAnswer;
	}

	public void setSelectedAnswer(final Answer selectedAnswer) {
		this.selectedAnswer = selectedAnswer;
	}

	public Question getSelectedQuestion() {
		return this.selectedQuestion;
	}

	public void setSelectedQuestion(final Question selectedQuestion) {
		this.selectedQuestion = selectedQuestion;
	}

	public Collection<Question> getQuestions() {
		return this.questions;
	}

	public void setQuestions(final Collection<Question> questions) {
		this.questions = questions;
	}
}
